import time
import random
import requests

from selenium import webdriver
from selenium.webdriver import ActionChains
from io import BytesIO
from PIL import Image
from collections import Counter
from selenium.webdriver import ChromeOptions
# 获取JD登陆页面
url = "https://passport.jd.com/new/login.aspx"
# 启动调试程序
option = ChromeOptions()
option.add_experimental_option("excludeSwitches", ['enable-automation'])
# 如何实现让selenium规避被检测的风险
browser = webdriver.Chrome(options = option)
# 通过浏览器的dev_tool在get页面钱将.webdriver属性改为"undefined"
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {       #直接滑块消失
    "source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})""",
})
# 二值化，将所有的点位，全
# 部换成0或255
def shape(w, h, image):
    tem = 0
    for x in range(w):
        for y in range(h):
            tem += image.getpixel((x, y))
    pixel_ave = tem / w / h * 0.7
    for x in range(w):
        for y in range(h):
            p = image.getpixel((x, y))
            if p < pixel_ave:
                image.putpixel((x, y), 0)
            else:
                image.putpixel((x, y), 255)
    return image

# 降噪处理
def reducenoise(image):
    w, h = image.size
    for x in range(0, 40):  # 处理最左边
        for y in range(h):
            image2 = image.putpixel((x, y), 255)
    return image

# 处理图片，灰度化与二值化、降噪
def make_picture():
    im = Image.open("code.png")
    im2 = im.convert("L")
    w, h = im2.size
    im3 = shape(w, h, im2)
    im4 = reducenoise(im3)
    return im4

# 计算距离
def get_juli(image):
    w, h = image.size
    ls = []
    for i in range(39, w - 39):  # 图片最左边放置滑块，缺口坐标x不可能小于31
        for j in range(10, h):
            if image.getpixel((i, j)) < 100:
                count = 0
                for k in range(i, i + 39):
                    if image.getpixel((k, j)) < 100:
                        count += 1
                    else:
                        break
                if count > 27: ls.append(i)
    return Counter(ls).most_common(1)[0][0]


# 设计拖动轨迹
def get_track(distance):
    v0 = 0
    t = 0.2
    tracks = []
    current = 0
    mid = distance * 4 / 5
    while current < distance:
        if current < mid:
            a = 2
        else:
            a = -3
        v = v0
        s = v * t + 0.5 * a * (t ** 2)
        current += s
        tracks.append(round(s))
        v0 = v + a * t
    jj = 0
    for i in tracks:
        jj += i
    ext = distance - jj
    print(ext)
    if ext == 0:
        pass
    elif ext > 0:
        for i in range(ext):
            tracks.append(1)
    else:
        for i in range(-ext):
            tracks.append(-1)
    return tracks

def drog_btn(track):  # 拖动滑块
    # 定位滑块
    ele = browser.find_element_by_xpath('.//div[@class="JDJRV-slide-inner JDJRV-slide-btn"]')
    # 设计拖动动作链（点击且不放）
    ActionChains(browser).click_and_hold(ele).perform()
    # 根据设计的轨迹，实现滑块拖动
    for i in track:
        ActionChains(browser).move_by_offset(i, 0).perform()
    # 睡眠0.25秒，伪装成人的判断过程
    time.sleep(0.5)
    # 释放滑块，类似于松开鼠标
    ActionChains(browser).release().perform()
    time.sleep(3)

def get_picture():
    username = "18296405761"
    password = "xxxxx"
    browser.get(url)
    browser.maximize_window()  # 全屏，很重要！！
    time.sleep(2)

    # 找到账户登录并且点击
    login_ele = browser.find_element_by_xpath("//div[@class='login-tab login-tab-r']")
    login_ele.click()
    time.sleep(2)

    # 输入用户名和密码
    username_ele = browser.find_element_by_xpath("//input[@id='loginname']")
    password_ele = browser.find_element_by_xpath("//input[@id='nloginpwd']")
    time.sleep(1)
    username_ele.send_keys(username)
    time.sleep(1)
    password_ele.send_keys(password)

    # 点击提交，进入滑动验证码页面
    submit_btn = browser.find_element_by_xpath("//a[@id='loginsubmit']")
    submit_btn.click()
    time.sleep(1)

def get_picture1():
    # 通过修改JS隐藏滑块并截屏获取验证码图片，保存至当前目录，名为code.png
    js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="none"'
    browser.execute_script(js)
    code_path = './code.png'
    browser.find_element_by_xpath('.//div[@class="JDJRV-bigimg"]').screenshot(code_path)
    time.sleep(1)
    # 停止1秒后恢复JS改动，回到页面最初状态
    js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="block"'
    browser.execute_script(js)

def check():  # 再次尝试
    get_picture1()
    image = make_picture()
    distance = get_juli(image)
    track = get_track(distance)
    drog_btn(track)

if __name__ == "__main__":
    get_picture()
    get_picture1()
    image = make_picture()
    distance = get_juli(image)
    track = get_track(distance)
    drog_btn(track)
    while True:
        if browser.current_url == "https://www.jd.com/":
            print("登录成功")
            break
        else:
            check()

